package myserver;

import dao.Dao;
import java.io.*;
import java.net.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.TreeSet;

import javax.swing.JOptionPane;


public class Server {
	private Socket s ;
	private ServerSocket ss;
	int port = 9002;
	int maxPort = 9002;
	//用来记录可用端口
	TreeSet<Integer> canUsePort = new TreeSet<Integer>();
	//file文件用来记录注册的用户
	public BufferedReader reader;
	/**多线程组，用来装连接的客户端的多线程
	 * */
	//用来装上线用户，包括用户名 和 线程
	HashMap<String,ServerThread> mapOnline = new HashMap<String,ServerThread>();
	
	//用来记录端口连接线程的个数
	int count=0;
	public ServerFileTransfer transfer = new ServerFileTransfer();
	public static void main(String[] args) {
		ServerFrame f = new ServerFrame();
		RegisterServer register = new RegisterServer();
		register.start();
		Server server = new Server();
		server.waitClient();
	}
	/**初始化所有数据库数据为不再线
	 */
	static{
		Dao.init();
	}
	
	/**用来等待客户端连接，发送端口号，关闭连接，循环等待新的客户端
	 * */
	private void waitClient() {
		try {
			ServerThread thread;
			while(true){
				ss = new ServerSocket(9001);
				s = ss.accept();
//				System.out.println("server:9001 is ok!");
				ServerFrame.area.append("server:9001 is ok!\n");
				BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
				PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8")),true);
				String num = reader.readLine();
				String pd = reader.readLine();
				int intRe = Dao.hasId(Integer.parseInt(num),pd);
				if(intRe !=1){
					writer.println(intRe+"");
//					System.out.println(intRe);
					ServerFrame.area.append(intRe+"\n");
					s.close();
					ss.close();
					continue;
				}
				writer.println(1+"");
				//用户名密码都正确，给用户发送新的可用端口
				int nowPort = getPort();
				writer.println(nowPort+"");
				thread = new ServerThread(this,num,nowPort);
				thread.start();
				mapOnline.put(num, thread);//加入上线列表
				sendChangeUser(num);//向它的好友发送自己已经上线了
				Dao.changeStatus(Integer.parseInt(num), 1);//在数据库中改变自己的状态
				ServerFrame.area.append("用户"+num+"上线了\n");
				s.close();
				ss.close();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**向他的好友发送自己状态改变的信息
	 */
	public  void sendChangeUser(String num){
		ResultSet result = Dao.getOnlineFriend(num);
		try {
			while(result.next()){
				ServerFrame.area.append(num+"  向自己的好友发送信息\n");
				ServerFrame.area.append(mapOnline.containsKey(num)+"\n");
				ServerFrame.area.append(num+"\n");
				ServerFrame.area.append(mapOnline.containsKey(result.getString("id"))+"\n");
				PrintWriter writer =mapOnline.get(result.getString("id")).writer;
				writer.println("server");
				writer.println("status");
				writer.println(num);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 获得能用的端口号
	 *@return int
	 * */
	int getPort(){
		if(canUsePort.isEmpty()){
			for(int i=maxPort;i<maxPort+100;i++)
				canUsePort.add(new Integer(i));
			maxPort += 100;//最大端口增加一百
		}
		return canUsePort.pollFirst().intValue();
		
	}
	
	/**
	 * 向所对应的客户端发送发送信息数据
	 * */
	public void sendMessage(String destID,String sourceID,String str){
		if(!mapOnline.containsKey(destID)){
			ServerFrame.area.append("用户没有上线，记录到数据库中\n");
			String strOld = "";
			if(Dao.hasWords(destID,sourceID))
				strOld = Dao.getWords(destID,sourceID);
			Dao.insertWords(destID,sourceID, str, strOld);
			ServerFrame.area.append("记录完毕\n");
			return;
		}
		ServerFrame.area.append("用户在线，要发送信息了\n");
		ServerThread sendThread = (ServerThread)mapOnline.get(destID);
		sendThread.writer.println(sourceID);//向客户端发送源数据名字 String
		ServerFrame.area.append("已经向客户端发送了源客户端名字: "+sourceID+"\n");
		String title = Dao.getName(sourceID)+"  "+new SimpleDateFormat("hh:mm:ss").format(new java.util.Date())+":\n";
		StringTokenizer tokens = new StringTokenizer(title+str,"\n",true);
		while(tokens.hasMoreTokens()){
			String strs =tokens.nextToken();
			sendThread.writer.print(strs);
			ServerFrame.area.append(strs+"\n");
		}
		sendThread.writer.println();
		ServerFrame.area.append("server+发送之前-->"+str+"\n");
		sendThread.writer.println("end");
		ServerFrame.area.append("已经向客户端发送了信息:  "+destID+"\n");
		
	}
}

/**多线程，用于建立和客户端的连接，接受并发送数据
 * */
class ServerThread extends Thread{
	private Server server ;
	private ServerSocket myServerSocket;
	private Socket mySocket;
	private BufferedReader reader;
	public PrintWriter writer;
	public int myPort;
	private String strID;
	ServerThread(Server server,String num,int port){
		this.server = server;
		this.strID = num;
		this.myPort = port;
	}
	public void run() {
		try {
			myServerSocket = new ServerSocket(myPort);
//ServerFrame.area.append("Sever 端口在等待："+myPort+"\n");
			mySocket = myServerSocket.accept();
//ServerFrame.area.append("server端已经连接上了\n");
			reader = new BufferedReader(new InputStreamReader(mySocket.getInputStream(),"UTF-8"));
			writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mySocket.getOutputStream(), "UTF-8")),true);
			
			//向客户端发送客户信息
			String message = Dao.getMessage(Integer.parseInt(strID));//数据中包括name pic
//ServerFrame.area.append(message+"\n");
			writer.println(message);
			//向客户端发送好友列表
			ResultSet set = Dao.getFriend(strID);
			try {
				while(set.next()){
					String s1 = set.getString(1)+","+set.getString(2)+","+set.getString(3)+","+set.getString(4)
				      +","+set.getString(5)+","+set.getString(6)+","+set.getString(7);
					writer.println(s1);
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			writer.println("end");
//ServerFrame.area.append("我已经向这个上线用户发送了好友列表了呀\n");
			
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
			//向客户发送曾经的旧消息
			while(Dao.hasWords(strID,"")){
ServerFrame.area.append("服务器检测到用户的好友曾经发送过信息\n");
				String sourceID = Dao.getSourceID(strID);
				server.sendMessage(strID, Dao.getSourceID(strID), Dao.getWords(strID,sourceID));
			}
			
			//while loop 直到中断，一直执行
			while(mySocket.isConnected()){
//ServerFrame.area.append("mySocket.isConnected() is true!\n");
				String strAll="";
				String destID=reader.readLine();
				String line;
				String huanhangfu = "";
				if(destID==null){
					throw new IOException("destId is null");
				}
				if(destID.equals("server")){//客户端向服务器发送的请求
					FromServer();//用forServer方法处理
					continue;
				}
				
				while((line=reader.readLine())!=null){//当接收到end时，表明本次发送结束
					if(line.equals("end")){
						huanhangfu = "";
						break;
					}
					strAll += huanhangfu+line;
					huanhangfu = "\n";
				}
				if(line==null){
					throw new IOException("gaga");
				}
				server.sendMessage(destID,strID,strAll);//向客户端发送消息
			}
//ServerFrame.area.append(strID+" 此线程完成，并回收\n");
			
		} catch (IOException e) {
//			e.printStackTrace();
		}finally{
ServerFrame.area.append("执行：finally\n");
			Dao.changeStatus(Integer.parseInt(strID), 0);
			server.canUsePort.add(myPort);
			server.sendChangeUser(strID);
			server.mapOnline.remove(strID);
			close();
		}
	}
	
	/**
	 * 	当接收到开头为Server的信息时进行逻辑处理
	 */
	private void FromServer(){
		try{
			String thingName = reader.readLine();
			//如果是Search好友的请求
			if(thingName.equals("searchFriend")){
				String idOrName = reader.readLine();
				if(idOrName.equals("ID")){
					int id1 = Integer.parseInt(reader.readLine());
					writer.println("server");
					writer.println("searchFriend");
					if(Dao.hasId(id1,"")==-1){
						writer.println("-1");
						return;
					}
					ResultSet set1 = Dao.getNewFriendMessage(id1+"");
					while(set1.next()){
						String s1 = set1.getString(1);
						String s2 = set1.getString(2);
						//id name
						writer.println(s1);
						writer.println(s2);
					}
					writer.println("end");
					
				}else if(idOrName.equals("name")){
					String name = reader.readLine();
					writer.println("server");
					writer.println("searchFriend");
					if(Dao.hasName(name)==-1){
						writer.println(-1);
						return;
					}
					ResultSet set1 = Dao.getNewFriendMessageName(name);
					while(set1.next()){
						String s1 = set1.getString(1);
						String s2 = set1.getString(2);
//						//id name
						writer.println(s1);
						writer.println(s2);
					}
					writer.println("end");
				}else if(idOrName.equals("con")){//条件查询
					String condition = reader.readLine();
					StringTokenizer tokens = new StringTokenizer(condition,",");
					String age = tokens.nextToken();
					String sex = tokens.nextToken();
					String city = tokens.nextToken();
					String isOnline = tokens.nextToken();
					int age1 = 0;
					int age2 = 0;
					if(age.length()==4){
						age1 = 0;
						age2 = 80;
					}else if(age.length()==5){
						age1 = Integer.parseInt(age.substring(0, 2));
						age2 = Integer.parseInt(age.substring(3, 5));
					}
//ServerFrame.area.append("age: "+age1+" "+age2+"\n");
					ResultSet set = Dao.getConditionMsg(age1,age2,sex,city,isOnline);
					writer.println("server");
					writer.println("searchFriend");
					boolean b = false;
					while(set.next()){
						b = true;
						String s1 = set.getString(1);
						String s2 = set.getString(2);
						writer.println(s1);
						writer.println(s2);
					}
					if(b)
						writer.println("end");
					else
						writer.println("-1");
					
				}
				return;
			}
			if(thingName.equals("addFriend")){//如果是添加好友的请求
				int id1 = Integer.parseInt(reader.readLine());
				writer.println("server");
				writer.println("addFriend");
				if(Dao.hasId(id1,"")==-1){
					writer.println("-1");
					return;
				}
				boolean b = Dao.addFriend(id1, Integer.parseInt(strID));
//ServerFrame.area.append("\n"+b);
				if(b){
					ServerFrame.area.append("\n"+"数据库添加成功");
					ResultSet set1 = Dao.getNewFriendMessage(id1+"");
					if(set1.next()){
						String s1 = set1.getString(1);
						String s2 = set1.getString(2);
						String s3 = set1.getString(3);
						String s4 = set1.getString(4);
						String s5 = set1.getString(5);
						String s6 = set1.getString(6);
						String s7 = set1.getString(7);
						writer.println("1");
						writer.println(s1);
						writer.println(s2);
						writer.println(s3);
						writer.println(s4);
						writer.println(s5);
						writer.println(s6);
						writer.println(s7);
					}
					return;
				}
//ServerFrame.area.append("\n"+"没有执行");
			}
			if(thingName.equals("deleteFriend")){//如果是删除好友的请求
				int id1 = Integer.parseInt(reader.readLine());
				Dao.deleteFriend(id1,Integer.parseInt(strID));
				writer.println("server");
				writer.println("deleteFriend");
				writer.println("1");
				writer.println(id1);
				return;
			}
			if(thingName.equals("set")){
				//读取 id name motto pic sex birthday city
				Dao.updateUser(reader.readLine(), reader.readLine(), reader.readLine(),
						reader.readLine(), reader.readLine(), reader.readLine(), reader.readLine());
			}
			if(thingName.equals("sendFile")){
ServerFrame.area.append("\n"+"sendFile");
				int friendID = Integer.parseInt(reader.readLine());
				String fileName = reader.readLine();
				//向好友发送server id fileName
ServerFrame.area.append("\n"+"sendFile-->friendID-->"+friendID);
				PrintWriter w = server.mapOnline.get(friendID+"").writer; 
				w.println("server");
				w.println("sendFile");
				w.println(strID);//发送发送文件的id
				w.println(fileName);
			}
			if(thingName.equals("receiveFile")){
				int friendID = Integer.parseInt(reader.readLine());
				String fileName = reader.readLine();
				String or = reader.readLine();
				PrintWriter w = server.mapOnline.get(friendID+"").writer;
				w.println("server");
				w.println("toFile");
				w.println(or);
				w.println(strID);
				w.println(fileName);
				if(or.equals("1")){
					int port1 = server.getPort();
					int num = server.transfer.getNum();
					w.println(port1);
					w.println(num);
					
					//再向接收端发送信息
					writer.println("server");
					writer.println("getFile");
					writer.println(friendID);
					writer.println(fileName);
					writer.println(port1);
					writer.println(num);
					
					//执行transfer的方法   执行两次，分别接受发送端 和接收端的连接
					//方法不好，需要改进  需要等待，应该改成并发执行的
					server.transfer.makeSocket(port1);
				}
			}
		}catch(IOException e){
			
		}catch(SQLException e){
			
		}
		
	}
	/**input output socket 的关闭,并返回给服务器自己的端口
	 * */
	private void close(){
		try {
			reader.close();
			myServerSocket.close();
			mySocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}